#pragma once
#include <map>
#include "..\ProgAdmin\AppObject.h"
#include "Species.h"
#define	 INDIVIDUAL   VirtualInvertedListTerm 
#define  Individual VirtualInvertedListTerm* 




class VirtualInvertedListTerm;
class	PopulationParameters : public AppObject{
public:
	size_t  MaxPopulationSize;
	time_t  MaxEvaluationTime;
	size_t  SelectionSize;
	size_t  EliteSize;
	size_t  MaxIndividualSize;
	double MutationProbability;

public:
	string toString( )const;
	void fromString(const char*);
};


class mapIndDoub : public map< Individual , double>{

public:
	const mapIndDoub& operator += (const mapIndDoub&);
	void eraseAll( );

	};

class Population
	{

	protected:
		size_t generationCount;
		PopulationParameters* Params;

	public:	
		typedef pair<Individual, double> IndFit;
		typedef double (*FitnessFunction)( INDIVIDUAL*, void*, time_t);
		typedef bool (*Ticker)(void); 
	
	protected:
		mapIndDoub m_Individuals;
		set<Individual> elite;
		Individual (*Generator)( void );
		Individual (*Spawn) (const Individual, const Individual);
		void (*Mutate) (Individual);

	public:
		/*Species are groups of actually or potentially 
		interbreeding natural populations which are reproductively 
		isolated from other such groups. Species are distinguished
		by the type of the first element of the inverted list*/
		vector< Species* > Taxonomie;

	public:
		Individual getSomeLuckyGuy( ) const;
		Individual getMate( Individual ) const;
		size_t removeDeadBeats( );

	protected:
		void mutate(Individual);
		void insert(Individual, double=0.0f);
		void insertMap(map<Individual, double>&);
	
	public:
		void goToNextGeneration(FitnessFunction, void*, vector<Ticker>);	
		void evaluateAll(FitnessFunction, void* , Ticker = NULL);
		void select( Ticker = NULL );
		void fillByBreeding( Ticker = NULL );		
		void fillByGenerating( Ticker = NULL);
				
	private:
		void destroy( );
	
	public:
		Population(		Individual (*)( void ),
							Individual (*) (const Individual, const Individual),
							void (*) (Individual),
							PopulationParameters*, 
							Ticker = NULL);
		virtual ~Population(void);
	
	public:
		IndFit operator[ ](const size_t&);
		size_t indexOf(Individual);
		size_t size( ) const;
		size_t getGenerationCount( )const{return this->generationCount;};
		
	public:
		void resetFitness( );
		map<double, pair<Individual, double> >*  normalizedFitnessStats( ) const;
		double sumFitness( ) const;
		double avgFitness( ) const;
		Individual getBest( );
		double getRawFitness(Individual Ind) const {
			return (m_Individuals.find(Ind))->second;
			};

	};





